#ifndef __IM_UTILITIES_H__
#define __IM_UTILITIES_H__

#include <im_base_types.h>

/**
 * @defgroup IMUtilities
 * @ingroup PublicIME
 * @{
 */

IM_BEGIN_DECLS

/**
 * @brief qsort an array, similar with qsort().
 *
 * The im_qsort_with_data() function sorts an array with total_elems of size size,
 * The base argument points to the start of the array.
 *
 * The contents of the array are sorted in ascending order according to a comparison
 * function pointed to by compare_func, which is called with three arguments that point
 * to the objects being compared and a pointer which holds datum the caller wants to 
 * pass with.
 *
 * The comparison function must return an integer less then, equal to, or
 * greater than zero if the first argument is considered to be respectively less than,
 * equal to, or greater than the second. If two members compare as equal, their order
 * in the sorted array is undefined.
 *
 * @param base Pointer of the array sorted in ascending order.
 * @param total_elems Total elements in the array.
 * @param size Size of each element.
 * @param compare_func Compare function.
 * @param user_data Arbitrary user data.
 *
 * @return The im_qsort_with_data() function shall not return a value
 */
void            im_qsort_with_data          (IMConstPointer         base,
                                             IMSize                 total_elems,
                                             IMSize                 size,
                                             IMCompareDataFunc      compare_func,
                                             IMPointer              user_data);

/**
 * @brief Finds the first position in which val could be inserted
 *        without changing the ordering.
 *
 *
 * The im_lower_bound() function searches for the first place that
 * val can be inserted into the ordered range defined by ...
 *
 * The comparison function shall return an integer less than, equal to, or
 * greater than zero if the first argument is considered to be respectively less than,
 * equal to, or greater than the second. If two members compare as equal, their order
 * in the sorted array is undefined.
 *
 * @param base Pointer of the array.
 * @param total_elems Total elements in the array.
 * @param size Size of each element.
 * @param val The element to be inserted.
 * @param compare_func Compare function.
 * @return A pointer to the first element "not less than" val, or end of
 *         the array if every element is less than val.
 *
 * @see im_lower_bound_with_data
 */
IMPointer       im_lower_bound              (IMConstPointer         base,
                                             IMSize                 total_elems,
                                             IMSize                 size,
                                             IMConstPointer         val,
                                             IMCompareFunc          compare_func);

/**
 * @brief Finds the last position in which val could be inserted
 *        without changing the ordering.
 *
 * The comparison function shall return an integer less than, equal to, or
 * greater than zero if the first argument is considered to be respectively less than,
 * equal to, or greater than the second. If two members compare as equal, their order
 * in the sorted array is undefined.
 *
 * @param base Pointer of the array.
 * @param total_elems Total elements in the array.
 * @param size Size of each element.
 * @param val The element to be inserted.
 * @param compare_func Compare function.
 * @return A pointer to the first element greater than val, or end of
 *         the array if no elements are greater than val.
 *
 * @see im_upper_bound_with_data
 */
IMPointer       im_upper_bound              (IMConstPointer         base,
                                             IMSize                 total_elems,
                                             IMSize                 size,
                                             IMConstPointer         val,
                                             IMCompareFunc          compare_func);

/**
 * @brief Finds the first position in which val could be inserted
 *        without changing the ordering.
 *
 * The comparison function shall return an integer less than, equal to, or
 * greater than zero if the first argument is considered to be respectively less than,
 * equal to, or greater than the second. If two members compare as equal, their order
 * in the sorted array is undefined.
 *
 * @param base Pointer of the array.
 * @param total_elems Total elements in the array.
 * @param size Size of each element.
 * @param val The element to be inserted.
 * @param compare_func Compare function.
 * @param user_data Arbitrary user data.
 * @return A pointer to the first element "not less than" val, or end of
 *         the array if every element is less than val.
 * @see im_upper_bound
 */
IMPointer       im_lower_bound_with_data    (IMConstPointer         base,
                                             IMSize                 total_elems,
                                             IMSize                 size,
                                             IMConstPointer         val,
                                             IMCompareDataFunc      compare_func,
                                             IMPointer              user_data);

/**
 * @brief Finds the last position in which val could be inserted
 *        without changing the ordering.
 *
 * The comparison function shall return an integer less than, equal to, or
 * greater than zero if the first argument is considered to be respectively less than,
 * equal to, or greater than the second. If two members compare as equal, their order
 * in the sorted array is undefined.
 *
 * @param base Pointer of the array.
 * @param total_elems Total elements in the array.
 * @param size Size of each element.
 * @param val The element to be inserted.
 * @param compare_func Compare function.
 * @param user_data Arbitrary user data.
 * @return A pointer to the first element greater than val, or end of
 *         the array if no elements are greater than val.
 */
IMPointer       im_upper_bound_with_data    (IMConstPointer         base,
                                             IMSize                 total_elems,
                                             IMSize                 size,
                                             IMConstPointer         val,
                                             IMCompareDataFunc      compare_func,
                                             IMPointer              user_data);
/**
 * @brief Returns prime numbers spaced by approximately 1.5-2.0.
 * 
 * It's for use in resizing data structures which prefer prime-valued sizes,
 * such as IMHashTable.
 *
 * @return the next largest prime, or the highest it knows about which is
 *         about MAXINT/4.
 */
IMUInt          im_spaced_primes_closest    (IMUInt                 num);

/**
 * @brief Calculate CRC32 checksum of a buffer.
 *
 * The im_calculate_crc32() function shall compute The CRC32 value.
 *
 * CRC32 value is caluculated with nbytes bytes from the data pointed to by buf.
 *
 *
 * @return The im_caluculate_crc32() function shall return CRC32 value generated with buf.
 * If buf is a null pointer or nbytes is 0, The im_calculate_crc32() function returns 0.
 */
IMUInt32        im_calculate_crc32          (const IMChar          *buf,
                                             IMSize                 nbytes);

IMUInt64        im_get_current_time_in_milliseconds ();

IM_END_DECLS
/** @} */

#endif
/*
vi:ts=4:nowrap:ai:expandtab
*/
